﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Shapes;

namespace GSI.Core
{
	class Track
	{
		/// <summary>
		/// 追踪
		/// </summary>
		public void DoTrack(MeshData mesh, double interval, DataGroup simpleData)
		{

			contourData = new Dictionary<double, List<Line>>();
			meshData = mesh.pointsArray;
			//将需要绘制的高程值保存好
			for (double value = 0; value < simpleData.MaxValue; value += interval)
			{
				if (value > simpleData.MinValue)
				{
					contourData.Add(value, new List<Line>());
				}

			}

			for (int n = 0; n < mesh.CellYNum; n++)
			{
				for (int m = 0; m < mesh.CellXNum; m++)
				{
					//对每一条需要绘制的高程值 进行网格遍历
					foreach (var contour in contourData)
					{
						switch (GetBinaryIndex(contour.Key, m, n))
						{
							#region 第一,二行
							case "0001":
							case "1110":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m, n, m, n + 1),
										CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1)));
								break;
							case "0010":
							case "1101":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m + 1, n, m + 1, n + 1),
										CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1)));
								break;
							case "0100":
							case "1011":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m, n, m + 1, n),
										CalExactPosition(contour.Key, m + 1, n + 1, m + 1, n)));
								break;
							case "1000":
							case "0111":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m, n, m + 1, n),
										CalExactPosition(contour.Key, m, n, m, n + 1)));
								break;

							#endregion

							#region 第三行

							case "0011":
							case "1100":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m, n, m, n + 1),
										CalExactPosition(contour.Key, m + 1, n, m + 1, n + 1)));
								break;
							case "0110":
							case "1001":
								contour.Value.Add(
									GetLine(
										CalExactPosition(contour.Key, m, n, m + 1, n),
										CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1)));
								break;

							#endregion

							#region 特殊情况，两条线

							case "1010":
								if (meshData[m + 1, n + 1].Value >= contour.Key)
								{
									contour.Value.Add(
										GetLine(
											CalExactPosition(contour.Key, m, n, m + 1, n),
											CalExactPosition(contour.Key, m + 1, n + 1, m + 1, n)));
									contour.Value.Add(
										GetLine(
											CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1),
											CalExactPosition(contour.Key, m, n + 1, m, n)));
								}
								else
								{
									contour.Value.Add(
										GetLine(CalExactPosition(contour.Key, m, n, m, n + 1),
										CalExactPosition(contour.Key, m, n, m + 1, n)));
									contour.Value.Add(
										GetLine(
											CalExactPosition(contour.Key, m + 1, n, m + 1, n + 1),
											CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1)));
								}
								break;
							case "0101":
								if (meshData[m + 1, n + 1].Value < contour.Key)
								{
									contour.Value.Add(
										GetLine(
											CalExactPosition(contour.Key, m, n, m + 1, n),
											CalExactPosition(contour.Key, m + 1, n + 1, m + 1, n)));
									contour.Value.Add(
										GetLine(
											CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1),
											CalExactPosition(contour.Key, m, n + 1, m, n)));
								}
								else
								{
									contour.Value.Add(
										GetLine(CalExactPosition(contour.Key, m, n, m, n + 1),
										CalExactPosition(contour.Key, m, n, m + 1, n)));
									contour.Value.Add(
										GetLine(CalExactPosition(contour.Key, m + 1, n, m + 1, n + 1),
										CalExactPosition(contour.Key, m + 1, n + 1, m, n + 1)));
								}
								break;

							#endregion

							case "PointinPolygon":
								break;
						}
					}
				}
			}
		}

		//需要绘制的高程值以及对应的线集合
		public Dictionary<double, List<Line>> contourData { set; get; }
		//初始化网格数据
		private GPoint[,] meshData;

		private Line GetLine(PointF pointF1, PointF pointF2)
		{
			return new Line {
				X1 = pointF1.X,
				X2 = pointF2.X,
				Y1 = pointF1.Y,
				Y2 = pointF2.Y
			};
		}

		private string GetBinaryIndex(double value, int X, int Y)
		{
			string result = null;

			result += meshData[X, Y].Value >= value ? "1" : "0";
			result += meshData[X + 1, Y].Value >= value ? "1" : "0";
			result += meshData[X + 1, Y + 1].Value >= value ? "1" : "0";
			result += meshData[X, Y + 1].Value >= value ? "1" : "0";

			return result;
		}

		private PointF CalExactPosition(double value, int startX, int startY, int endX, int endY)
		{
			double radio = ((value - meshData[startX, startY].Value) / (meshData[endX, endY].Value - meshData[startX, startY].Value));
			return new PointF((float)(meshData[startX, startY].X + radio * (meshData[endX, endY].X - meshData[startX, startY].X)),
							  (float)(meshData[startX, startY].Y + radio * (meshData[endX, endY].Y - meshData[startX, startY].Y)));
		}


	}
}
